package com.chipcoo.utils;

import java.net.URLEncoder;
import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;

public final class StringUtils {
    public static int nextInt(final int min, final int max) {
        Random rand = new Random();
        int tmp = Math.abs(rand.nextInt());
        return tmp % (max - min + 1) + min;
    }
    public static boolean isEmpty(String text){
        if(null==text) return true;
        return text.trim().length()==0;
    }
    public static long ip2long(String text){
        if(isEmpty(text)) return 0;
        else{

            String[] ipAddressInArray = text.split("\\.");
            long result = 0;
            try {
                result  = Integer.parseInt(ipAddressInArray[3]) & 0xFF;
                result |= ((Integer.parseInt(ipAddressInArray[2]) << 8) & 0xFF00);
                result |= ((Integer.parseInt(ipAddressInArray[1])<< 16) & 0xFF0000);
                result |= ((Long.parseLong(ipAddressInArray[0]) << 24) & 0xFF000000L);

            }catch (Exception ex){
                result=0;
            }
            return result;
        }
    }
    public static String long2ip(long ip) {
        StringBuilder result = new StringBuilder(15);
        for (int i = 0; i < 4; i++) {
            result.insert(0,Long.toString(ip & 0xff));
            if (i < 3) result.insert(0,'.');
            ip = ip >> 8;
        }
        return result.toString();
    }
    private static long getIPMask(int code){
        if(code<0||code>=32)return  0xFFFFFFFFL;
        long mask =0;
        for(int i=0;i<=code;i++) mask |= 0x1L<<(32-i);
        return mask;
    }
    private static boolean isIPV4(String text){
        if(null==text||text.length()<=0) return  false;
        else {
            return Pattern.matches("^(((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))(/((\\d)|([1-2]\\d)|(3[0-2])))?$" ,text.trim());
        }
    }
    public static boolean ip1belongip2(String ip1,String ip2WithMaskCode){
        if(!isIPV4(ip1)) return  false;
        if(!isIPV4(ip2WithMaskCode)) return false;

        long mask; int maskIndex;
        if( (maskIndex = ip2WithMaskCode.indexOf('/'))>0)  mask = getIPMask(Integer.parseInt(ip2WithMaskCode.substring(maskIndex + 1)));
        else mask = 0xFFFFFFFFL;

        return  (ip2long(ip1)&mask) == (ip2long(ip2WithMaskCode)&mask);
    }



    public static String decodeUnicode(String text){
        char aChar;
        int len = text.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len;) {
            aChar = text.charAt(x++);
            if (aChar == '\\') {
                aChar = text.charAt(x++);
                if (aChar == 'u') {
                    // Read the xxxx
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = text.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException("Malformed   \\uxxxx   encoding.");
                        }
                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't')
                        aChar = '\t';
                    else if (aChar == 'r')
                        aChar = '\r';
                    else if (aChar == 'n')
                        aChar = '\n';
                    else if (aChar == 'f')
                        aChar = '\f';
                    outBuffer.append(aChar);
                }
            } else
                outBuffer.append(aChar);
        }
        return outBuffer.toString();
    }



    private final static char[] DIGITS_64 = {
            'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'g', 'h', 'i', 'j', 'k',
            '-', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'


    };
    private final static int digitWithC64(char c){
        for(int x=0;x<DIGITS_64.length;x++) {
            if (DIGITS_64[x] == c) {
                return x;
            }
        }
        return -1;
    }
    /**
     * ZZZZZZ （Z占位6，最多占位36位）
     * @param i
     * @return
     */
    public static String i2radix64(int i) {
        if(i<0) return null;
        int radix=64;
        char buf[] = new char[6];int charPos = 5;
        while (i>=radix) {
            buf[charPos--] = DIGITS_64[i%radix];
            i = i / radix;
        }

        if(charPos>=0) buf[charPos] = DIGITS_64[i];
        return new String(buf, charPos, (6 - charPos));
    }
    public static int radix642i(String text){
        if(null==text) return 0;
        text=text.trim();
        if(text.length()<=0) return 0;

        int result = 0;
        int index=0,len=text.length();
        int digit;
        while (index<len){
            char c = text.charAt(index++);
            digit = digitWithC64(c);
            if(digit>=0) {
                result *= 64;
                result += digit;
            }
        }
        return result;
    }
    public static String toBase64(String text) {
        if(null==text||text.length()<=0) return null;
        return toBase64(text.getBytes());
    }
    public static String toBase64(byte[] buffer){
        if(null==buffer||buffer.length==0)return null;

        StringBuilder sb = new StringBuilder();
        //region 全局3-4字节
        int iIndex=0;
        int iData;

        for(int i=0;i<buffer.length/3;i++){
            //region 构建3字节 整数

            iData = buffer[iIndex++];

            iData=iData<<8;
            iData|=(buffer[iIndex++]&0xFF);
            iData=iData<<8;
            iData|=(buffer[iIndex++]&0xFF);
            //endregion

            //region 方向输出 3*8=4*6=24位 6位用一个C显示
            sb.append(DIGITS_64[iData&0x3F]);

            iData=iData>>6;
            sb.append(DIGITS_64[iData&0x3F]);

            iData=iData>>6;
            sb.append(DIGITS_64[iData&0x3F]);

            iData=iData>>6;
            sb.append(DIGITS_64[iData&0x3F]);

        }
        //endregion

        //region 结尾处理
        iData=0;

        switch (buffer.length%3){
            case 0:
                break;
            case 1://单字节->双字节 255                                   8<2*6;
                iData = buffer[iIndex++];
                sb.append(DIGITS_64[iData&0x3F]);
                iData = iData >> 6;
                sb.append(DIGITS_64[iData&0x3F]);
                break;
            case 2: //双字节->3字节  255->65535                            2*8<=3*6
                iData = buffer[iIndex++];
                iData = iData << 8;
                iData = iData | buffer[iIndex++];
                sb.append(DIGITS_64[iData&0x3F]);
                iData = iData >> 6;
                sb.append(DIGITS_64[iData&0x3F]);
                iData = iData >> 6;
                sb.append(DIGITS_64[iData&0x3F]);
                break;
        }
        //endregion
        return sb.toString();
    }
    public static String decodeBase64(String text){
        if(null==text) return null;
        text =text.trim();
        int len =text.length();
        if(len<2) return null;
        int sizePadding =len%4;
        int size = len/4;
        int sizeFixed = size*3;
        if(sizePadding==2) sizeFixed++;
        else if(sizePadding==3) sizeFixed+=2;

        byte[] buffer = new byte[sizeFixed];

        int iIndex=0,iBuffer=0;
        int iPack,digit;
        for(int i=0;i<size;i++){
            iPack=0;
            for(int j=0;j<4;j++){
                digit = digitWithC64(text.charAt(iIndex++));
                if(digit>=0) {
                    digit = digit<< 6*j;
                    iPack |= digit;
                }
            }

            /*buffer[iBuffer + 2] = (byte)iPack;
            iPack = iPack >> 8;
            buffer[iBuffer + 1] = (byte)iPack;
            iPack = iPack >> 8;
            buffer[iBuffer] = (byte)iPack;

            iBuffer += 3;*/
            buffer[iBuffer++] = (byte) (iPack>>16);
            buffer[iBuffer++] = (byte) (iPack>>8);
            buffer[iBuffer++] = (byte) iPack;
        }


        if(sizePadding>=2){
            iPack = 0;
            for(int i=0;i<sizePadding;i++){
                digit = digitWithC64(text.charAt(iIndex++));
                if(digit>0){
                    digit = digit<<i*6;
                    iPack |=digit;
                }
            }

            if(sizePadding==3) buffer[iBuffer++] = (byte)(iPack>>8);
            buffer[iBuffer++] = (byte)iPack;
        }
        return  new String(buffer);
        /*try {
            return  new String(buffer,"utf-8");
        }catch (Exception ex)
        {
            ex.printStackTrace();
            return  null;
        }*/
    }


    public static void buildURLQueries(StringBuilder targetUrl, Map model, String encodingScheme)  {
        String fragment = null;
        int anchorIndex = targetUrl.toString().indexOf('#');
        if (anchorIndex > -1) {
            fragment = targetUrl.substring(anchorIndex);
            targetUrl.delete(anchorIndex, targetUrl.length());
        }
        // If there aren't already some parameters, we need a "?".
        boolean first = (targetUrl.toString().indexOf('?') < 0);
        Map queryProps = model;
        if (queryProps != null) {
            for (Object o : queryProps.entrySet()) {

                if (first) {
                    targetUrl.append('?');
                    first = false;
                } else {
                    targetUrl.append('&');
                }
                Map.Entry entry = (Map.Entry) o;
                try {
                    String encodedKey = URLEncoder.encode(entry.getKey().toString(), encodingScheme);
                    String encodedValue = (entry.getValue() != null ? URLEncoder.encode(entry.getValue().toString(), encodingScheme) : "");
                    targetUrl.append(encodedKey).append('=').append(encodedValue);
                }catch (Exception ex){

                }

            }
        }
        // Append anchor fragment, if any, to end of URL.
        if (fragment != null) {
            targetUrl.append(fragment);
        }
    }
}